home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 12 / Example 12.3 / effect.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-06-30  |  10.8 KB  |  345 lines

  1. #include "effect.h"
  2.  
  3. //Global Effect variables
  4. ID3DXMesh *billboardMesh = NULL;
  5. D3DMATERIAL9 whiteMtrl;
  6. SHADER effectVertexShader, effectPixelShader;
  7. D3DXHANDLE effectMatW, effectMatVP, effectVCol;
  8.  
  9. //Global Effect Textures
  10. IDirect3DTexture9* runesTexture = NULL;
  11. IDirect3DTexture9* cloudTexture = NULL;
  12. IDirect3DTexture9* fireballTexture = NULL;
  13.  
  14. struct SimpleVertex
  15. {
  16.     SimpleVertex(){}
  17.     SimpleVertex(D3DXVECTOR3 pos, D3DXVECTOR3 norm, D3DXVECTOR2 _uv)
  18.     {
  19.         position = pos;
  20.         normal = norm;
  21.         uv = _uv;
  22.     }
  23.  
  24.     D3DXVECTOR3 position, normal;
  25.     D3DXVECTOR2 uv;
  26.  
  27.     static const DWORD FVF;
  28. };
  29.  
  30. const DWORD SimpleVertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
  31.  
  32. void LoadEffectResources(IDirect3DDevice9 *m_pDevice)
  33. {
  34.     //Calculate sight mesh (a simple quad)
  35.     D3DXCreateMeshFVF(2, 4, D3DXMESH_MANAGED, SimpleVertex::FVF, m_pDevice, &billboardMesh);
  36.  
  37.     //Create 4 vertices
  38.     SimpleVertex* v = 0;
  39.     billboardMesh->LockVertexBuffer(0,(void**)&v);
  40.     v[0] = SimpleVertex(D3DXVECTOR3(-0.5f, 0.0f, 0.5f), D3DXVECTOR3(0.0f, 1.0f, 0.0f), D3DXVECTOR2(0, 0));
  41.     v[1] = SimpleVertex(D3DXVECTOR3( 0.5f, 0.0f, 0.5f), D3DXVECTOR3(0.0f, 1.0f, 0.0f), D3DXVECTOR2(1, 0));
  42.     v[2] = SimpleVertex(D3DXVECTOR3(-0.5f, 0.0f, -0.5f),D3DXVECTOR3(0.0f, 1.0f, 0.0f), D3DXVECTOR2(0, 1));
  43.     v[3] = SimpleVertex(D3DXVECTOR3( 0.5f, 0.0f, -0.5f),D3DXVECTOR3(0.0f, 1.0f, 0.0f), D3DXVECTOR2(1, 1));
  44.     billboardMesh->UnlockVertexBuffer();
  45.  
  46.     //Create 2 faces
  47.     WORD* indices = 0;
  48.     billboardMesh->LockIndexBuffer(0,(void**)&indices);    
  49.     indices[0] = 0; indices[1] = 1; indices[2] = 2;
  50.     indices[3] = 1; indices[4] = 3; indices[5] = 2;
  51.     billboardMesh->UnlockIndexBuffer();
  52.  
  53.     //Set Attributes for the 2 faces
  54.     DWORD *att = 0;
  55.     billboardMesh->LockAttributeBuffer(0,&att);
  56.     att[0] = 0; att[1] = 0;
  57.     billboardMesh->UnlockAttributeBuffer();
  58.  
  59.     //Sight MTRL
  60.     memset(&whiteMtrl, 0, sizeof(D3DMATERIAL9));
  61.     whiteMtrl.Diffuse = whiteMtrl.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
  62.  
  63.     //Load Shaders
  64.     effectVertexShader.Init(m_pDevice, "shaders/effect.vs", VERTEX_SHADER);
  65.     effectPixelShader.Init(m_pDevice, "shaders/effect.ps", PIXEL_SHADER);
  66.  
  67.     //Get constants
  68.     effectMatW = effectVertexShader.GetConstant("matW");
  69.     effectMatVP = effectVertexShader.GetConstant("matVP");
  70.     effectVCol = effectVertexShader.GetConstant("vertexColor");
  71.  
  72.     //Load textures
  73.     D3DXCreateTextureFromFile(m_pDevice, "textures/runes.dds", &runesTexture);
  74.     D3DXCreateTextureFromFile(m_pDevice, "textures/cloud.dds", &cloudTexture);
  75.     D3DXCreateTextureFromFile(m_pDevice, "textures/fireball.dds", &fireballTexture);
  76. }
  77.  
  78. void UnloadEffectResources()
  79. {
  80.     if(billboardMesh)billboardMesh->Release();
  81.     billboardMesh = NULL;
  82.  
  83.     //Release textures
  84.     if(runesTexture)runesTexture->Release();
  85.     if(cloudTexture)cloudTexture->Release();
  86.     if(fireballTexture)fireballTexture->Release();
  87.  
  88.     runesTexture = NULL;
  89.     cloudTexture = NULL;
  90.     fireballTexture = NULL;
  91. }
  92.  
  93. //////////////////////////////////////////////////////////////////////////////////////////////
  94. //                                TRANSFORM                                                    //
  95. //////////////////////////////////////////////////////////////////////////////////////////////
  96.  
  97. TRANSFORM::TRANSFORM(){ m_pos = m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f); m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f); }
  98. TRANSFORM::TRANSFORM(D3DXVECTOR3 _pos){ m_pos = _pos; m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f); m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f); }
  99. TRANSFORM::TRANSFORM(D3DXVECTOR3 _pos, D3DXVECTOR3 _rot){ m_pos = _pos; m_rot = _rot; m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f); }
  100. TRANSFORM::TRANSFORM(D3DXVECTOR3 _pos, D3DXVECTOR3 _rot, D3DXVECTOR3 _sca){ m_pos = _pos; m_rot = _rot; m_sca = _sca; }
  101.  
  102. void TRANSFORM::Init(D3DXVECTOR3 _pos){ m_pos = _pos; m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f); m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f); }
  103. void TRANSFORM::Init(D3DXVECTOR3 _pos, D3DXVECTOR3 _rot){ m_pos = _pos; m_rot = _rot; m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f); }
  104. void TRANSFORM::Init(D3DXVECTOR3 _pos, D3DXVECTOR3 _rot, D3DXVECTOR3 _sca){ m_pos = _pos; m_rot = _rot; m_sca = _sca; }
  105.  
  106. D3DXMATRIX TRANSFORM::GetWorldMatrix()
  107. {
  108.     D3DXMATRIX p, r, s;
  109.     D3DXMatrixTranslation(&p, m_pos.x, m_pos.y, m_pos.z);
  110.     D3DXMatrixRotationYawPitchRoll(&r, m_rot.y, m_rot.x, m_rot.z);
  111.     D3DXMatrixScaling(&s, m_sca.x, m_sca.y, m_sca.z);
  112.     D3DXMATRIX world = s * r * p;
  113.     return world;
  114. }
  115.  
  116. //////////////////////////////////////////////////////////////////////////////////////////////
  117. //                                EFFECTS    BASE CLASS                                            //
  118. //////////////////////////////////////////////////////////////////////////////////////////////
  119.  
  120. EFFECT::EFFECT(IDirect3DDevice9 *Dev)
  121. {
  122.     m_pDevice = Dev;
  123.     m_time = 0.0f;
  124.     m_color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);    //White
  125. }
  126.  
  127. void EFFECT::PreRender()
  128. {
  129.     //Enable alpha blending
  130.     m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  131.     m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  132.     m_pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  133.     m_pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  134.     m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
  135.     m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  136.     m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE );
  137.     m_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  138.     m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, false);
  139.     m_pDevice->SetRenderState(D3DRS_LIGHTING, false);
  140.  
  141.     //Set vertex shader variables
  142.     D3DXMATRIX view, proj;
  143.     m_pDevice->GetTransform(D3DTS_VIEW, &view);
  144.     m_pDevice->GetTransform(D3DTS_PROJECTION, &proj);
  145.     
  146.     effectVertexShader.SetMatrix(effectMatVP, view * proj);
  147.     effectVertexShader.SetVector4(effectVCol, m_color);
  148.  
  149.     //Set material
  150.     m_pDevice->SetMaterial(&whiteMtrl);
  151.  
  152.     //enable Shaders
  153.     effectVertexShader.Begin();
  154.     effectPixelShader.Begin();
  155. }
  156.  
  157. void EFFECT::PostRender()
  158. {
  159.     //Reset renderstates
  160.     m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
  161.     m_pDevice->SetRenderState(D3DRS_ZWRITEENABLE, true);
  162.     m_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
  163.  
  164.     //Disable shaders
  165.     effectVertexShader.End();
  166.     effectPixelShader.End();
  167. }
  168.  
  169. //////////////////////////////////////////////////////////////////////////////////////////////
  170. //                                EFFECTS    SPELL                                                //
  171. //////////////////////////////////////////////////////////////////////////////////////////////
  172.  
  173. EFFECT_SPELL::EFFECT_SPELL(IDirect3DDevice9 *Dev, D3DXVECTOR3 _pos) : EFFECT(Dev), m_t1(_pos, D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DXVECTOR3(0.1f, 0.1f, 0.1f))
  174. {
  175.     m_t1.m_pos.y += 1.0f;
  176.     m_color = D3DXVECTOR4(rand()%1000 / 1000.0f, rand()%1000 / 1000.0f, rand()%1000 / 1000.0f, 0.0f);
  177.  
  178.     for(int i=0;i<10;i++)
  179.     {
  180.         float angle = i * (D3DX_PI / 5.0f);
  181.             
  182.         m_c[i].Init(_pos + D3DXVECTOR3(cos(angle) * 0.5f, 2.5f, sin(angle) * 0.5f),
  183.                   D3DXVECTOR3(D3DX_PI * 0.5f, angle, 0.0f),
  184.                   D3DXVECTOR3(4.0f, 4.0f, 6.0f));
  185.     }
  186. }
  187.  
  188. void EFFECT_SPELL::Update(float timeDelta)
  189. {
  190.     m_time += timeDelta;
  191.  
  192.     //Update Lower spinning quad...
  193.     m_t1.m_rot.y += timeDelta;
  194.  
  195.     //Update cloud
  196.     for(int i=0;i<10;i++)
  197.         m_c[i].m_rot.y -= timeDelta;
  198.  
  199.     //Update Spinning quad scale
  200.     if(m_time < 1.5f)m_t1.m_sca += D3DXVECTOR3(timeDelta, timeDelta, timeDelta) * 4.0f;
  201.     if(m_time > 4.5f)m_t1.m_sca -= D3DXVECTOR3(timeDelta, timeDelta, timeDelta) * 4.0f;
  202.  
  203.     //Calculate alpha
  204.     m_color.w = m_t1.m_sca.x / 6.0f;
  205. }
  206.  
  207. void EFFECT_SPELL::Render()
  208. {
  209.     PreRender();
  210.  
  211.     if(billboardMesh)
  212.     {
  213.         //Spinning quad
  214.         m_pDevice->SetTexture(0, runesTexture);
  215.         effectVertexShader.SetMatrix(effectMatW, m_t1.GetWorldMatrix());
  216.         billboardMesh->DrawSubset(0);
  217.  
  218.         //Cloud
  219.         m_pDevice->SetTexture(0, cloudTexture);
  220.         for(int i=0;i<10;i++)
  221.         {
  222.             effectVertexShader.SetMatrix(effectMatW, m_c[i].GetWorldMatrix());
  223.             billboardMesh->DrawSubset(0);
  224.         }
  225.     }
  226.  
  227.     PostRender();
  228. }
  229.  
  230. bool EFFECT_SPELL::isDead()
  231. {
  232.     return m_t1.m_sca.x < 0.0f;
  233. }
  234.  
  235. //////////////////////////////////////////////////////////////////////////////////////////////
  236. //                                EFFECTS    FIREBALL                                            //
  237. //////////////////////////////////////////////////////////////////////////////////////////////
  238.  
  239. EFFECT_FIREBALL::EFFECT_FIREBALL(IDirect3DDevice9 *Dev, BONE *_src, D3DXVECTOR3 _dest) : EFFECT(Dev)
  240. {
  241.     m_pSrcBone = _src;
  242.     m_dest = _dest;
  243.     m_color.w = 0.01f;
  244.     m_prc = 0.0f;
  245.     m_speed = 22.0f;
  246.  
  247.     if(m_pSrcBone != NULL)
  248.     {
  249.         D3DXMATRIX mat = m_pSrcBone->CombinedTransformationMatrix;        
  250.         m_t1.Init(D3DXVECTOR3(mat(3,0), mat(3, 1), mat(3, 2)), D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DXVECTOR3(0.1f, 0.1f, 0.1f));
  251.     }
  252. }
  253.  
  254. void EFFECT_FIREBALL::Update(float timeDelta)
  255. {
  256.     m_t1.m_rot += D3DXVECTOR3(0.5f, 0.5f, 0.5f) * timeDelta;
  257.  
  258.     if(m_time < 1.0f && m_pSrcBone != NULL)        //Follow staff
  259.     {
  260.         m_time += timeDelta;
  261.         D3DXMATRIX mat = m_pSrcBone->CombinedTransformationMatrix;
  262.         m_t1.m_pos = D3DXVECTOR3(mat(3,0), mat(3, 1), mat(3, 2));        //Extract position from bone
  263.         m_t1.m_sca = D3DXVECTOR3(1.5f, 1.5f, 1.5f) * m_time;
  264.         m_color.w = m_time;
  265.  
  266.         if(m_time > 1.0f)
  267.         {
  268.             m_color.w = m_time * 0.5f;
  269.             m_origin = m_t1.m_pos;
  270.             m_length = D3DXVec3Length(&(m_origin - m_dest));
  271.         }
  272.     }
  273.     else if(m_prc < 1.0f)        //Fly towards target
  274.     {
  275.         m_prc += (m_speed * timeDelta) / m_length;
  276.         m_t1.m_pos = GetPosition(m_prc);
  277.     }
  278.     else                    //Explode
  279.     {
  280.         m_prc += (m_speed * timeDelta) / m_length;
  281.         m_t1.m_sca += D3DXVECTOR3(5.0f, 5.0f, 5.0f) * timeDelta;
  282.         m_color.w -= timeDelta * 0.5f;
  283.     }
  284. }
  285.  
  286. void EFFECT_FIREBALL::Render()
  287. {
  288.     PreRender();
  289.  
  290.     if(billboardMesh)
  291.     {
  292.         D3DXVECTOR3 orgRot = m_t1.m_rot;
  293.         D3DXVECTOR3 rotations[] = {D3DXVECTOR3(0.0f, 0.0f, 0.0f),
  294.                                    D3DXVECTOR3(D3DX_PI * 0.5f, 0.0f, 0.0f),
  295.                                    D3DXVECTOR3(0.0f, D3DX_PI * 0.5f, 0.0f),
  296.                                    D3DXVECTOR3(0.0f, 0.0f, D3DX_PI * 0.5f)};
  297.  
  298.         D3DXVECTOR3 orgPos = m_t1.m_pos;
  299.         D3DXVECTOR3 positions[] = {m_t1.m_pos, 
  300.                                    GetPosition(m_prc - (1.5f / m_length)),
  301.                                    GetPosition(m_prc - (2.5f / m_length)),
  302.                                    GetPosition(m_prc - (3.25f / m_length)),
  303.                                    GetPosition(m_prc - (4.0f / m_length))};
  304.  
  305.         D3DXVECTOR3 orgSca = m_t1.m_sca;
  306.         D3DXVECTOR3 scales[] = {m_t1.m_sca, 
  307.                                 m_t1.m_sca * 0.8f,
  308.                                 m_t1.m_sca * 0.6f,
  309.                                 m_t1.m_sca * 0.4f,
  310.                                 m_t1.m_sca * 0.2f};
  311.     
  312.         m_pDevice->SetTexture(0, fireballTexture);
  313.         for(int t=0;t<5;t++)
  314.             for(int i=0;i<4;i++)
  315.             {
  316.                 m_t1.m_pos = positions[t];
  317.                 m_t1.m_rot = orgRot + rotations[i];
  318.                 m_t1.m_sca = scales[t];
  319.  
  320.                 effectVertexShader.SetMatrix(effectMatW, m_t1.GetWorldMatrix());
  321.                 billboardMesh->DrawSubset(0);
  322.             }
  323.  
  324.         m_t1.m_pos = orgPos;
  325.         m_t1.m_rot = orgRot;
  326.         m_t1.m_sca = orgSca;
  327.     }
  328.  
  329.     PostRender();
  330. }
  331.  
  332. bool EFFECT_FIREBALL::isDead()
  333. {
  334.     return m_pSrcBone == NULL || m_color.w < 0.0f;
  335. }
  336.  
  337. D3DXVECTOR3 EFFECT_FIREBALL::GetPosition(float p)
  338. {
  339.     if(p < 0.0f)p = 0.0f;
  340.     if(p > 1.0f)p = 1.0f;
  341.  
  342.     D3DXVECTOR3 m_pos = m_origin * (1.0f - p) + m_dest * p;    //Lerp between origin and dest
  343.     m_pos.y += sin(p * D3DX_PI) * 3.0f;                        //Add Arc
  344.     return m_pos;
  345. }